﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AnguaRPGEngine.Library.Parts;
using AnguaRPGEngine.Library.Systems;
using AnguaRPGEngine.Library.Interfaces;
using AnguaRPGEngine.Library.Forms;
using AnguaRPGEngine.Library.Events;
using AnguaRPGEngine.Library.Events.Messages;
using log4net;
using System.Reflection;

namespace AnguaRPGEngine.Library.Controls
{
    /// <summary>
    /// This control is used in the Map Editor, GM Client, and PC Client for displaying the map parts.
    /// In the Map Editor, it is placed in Edit Mode and allows the user to create and edit maps.
    /// In the GM client it allows movement of counters and toggling of visibility of parts
    /// In the PC client it allows movement of player owned counters and only displays parts that are visible to PCs
    /// </summary>
    public partial class MapControl : UserControl, IHandleMessagesOfType<SelectedPartChangeEvent>, IHandleMessagesOfType<SelectedPartTypeChangeEvent>
    {
        #region Private Properties and Objects
        private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private EditorTools _EditorTools; // this is the form containing the editing tools for the map
        private PartTypes _SelectedPartType; // this controls which layer the user is editing
        private float _ClockwiseRotation = 0f; // this is a value for animation of parts to rotate clockwise
        private float _CounterclockwiseRotation = 0f; // this is a value for animation of parts to rotate counter clockwise
        private Point _ViewTopLeft = new Point(0, 0); // this is the gameboard space that is in the top left of the map control
        private Point _BoardPoint = new Point(0, 0); // this is the gameboard space that is under the mouse cursor
        private Rectangle _ViewRectangle = new Rectangle(0, 0, 0, 0); // this is extend of the gameboard viewable in the map control
        private List<IPart> _Parts = new List<IPart>(); // this is the list of map parts to be displayed
        private int _EditingPartIndex = -1; // this is the part that is being edited (only available in edit mode)
        private Counter _SelectedCounter = null; // this is the part (counter) that is currently selected, enabling move mode.
        private int _ScrollSpeed = 10;
        private int _ScrollIndex = 0;
        private int _DeltaX = 0;
        private int _DeltaY = 0;
        private bool _ScrollOn = false;
        private bool _BitmapOnly;
        #endregion
        #region Public Properties and Objects
        public bool BitmapOnly
        {
            get
            {
                return _BitmapOnly;
            }
            set
            {
                _BitmapOnly = value;
            }
        }
        public bool EditMode; // this determines if the map control parts are editable
        public IPart SelectedPart = null; // this is the part that is selected in the parts tool bar from the Map Editor form
        public bool GMMode; // this determines if visibility is editable without allowing the entire map to be editable
        public Guid PlayerGuid; // this determines if visibility items are considered as well as limiting counter selection to ones belonging to this Player 
        #region Parts
        /// <summary>
        /// Public exposer of the IPart list
        /// </summary>
        public List<IPart> Parts
        {
            set
            {
                _Parts = value;
            }
            get
            {
                return _Parts;
            }
        }
        #endregion
        #endregion
        #region ctor
        /// <summary>
        /// Map Control constructor #1, called from GM client
        /// </summary>
        public MapControl()
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                this.GMMode = true;
                this.EditMode = false;
                _EditorTools = new EditorTools();
                _EditorTools.DeleteClicked += new EditorTools.DeleteClickEventHandler(_EditorTools_DeleteClicked);
                _EditorTools.RotateClockwiseClicked += new EditorTools.RotateClockwiseClickEventHandler(_EditorTools_RotateClockwiseClicked);
                _EditorTools.RotateCounterClockwiseClicked += new EditorTools.RotateCounterClockwiseClickEventHandler(_EditorTools_RotateCounterClockwiseClicked);
                this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.Opaque, true);
                InitializeComponent();
                ApplicationController.EventAggregator.RegisterListener(this);
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }

        /// <summary>
        /// Map Control constructor #2, you can pass editable boolean through here
        /// </summary>
        /// <param name="editMode"></param>
        public MapControl(bool editMode)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                this.GMMode = false;
                this.EditMode = editMode;
                _EditorTools = new EditorTools();
                _EditorTools.DeleteClicked += new EditorTools.DeleteClickEventHandler(_EditorTools_DeleteClicked);
                _EditorTools.RotateClockwiseClicked += new EditorTools.RotateClockwiseClickEventHandler(_EditorTools_RotateClockwiseClicked);
                _EditorTools.RotateCounterClockwiseClicked += new EditorTools.RotateCounterClockwiseClickEventHandler(_EditorTools_RotateCounterClockwiseClicked);
                this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.Opaque, true);
                InitializeComponent();
                ApplicationController.EventAggregator.RegisterListener(this);
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }
        /// <summary>
        /// Map Control constructor #2, you can pass player GUID through here
        /// </summary>
        /// <param name="editMode"></param>
        public MapControl(Guid playerGuid)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                this.GMMode = false;
                this.PlayerGuid = playerGuid;
                this.EditMode = false;
                _EditorTools = new EditorTools();
                _EditorTools.DeleteClicked += new EditorTools.DeleteClickEventHandler(_EditorTools_DeleteClicked);
                _EditorTools.RotateClockwiseClicked += new EditorTools.RotateClockwiseClickEventHandler(_EditorTools_RotateClockwiseClicked);
                _EditorTools.RotateCounterClockwiseClicked += new EditorTools.RotateCounterClockwiseClickEventHandler(_EditorTools_RotateCounterClockwiseClicked);
                this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.Opaque, true);
                InitializeComponent();
                ApplicationController.EventAggregator.RegisterListener(this);
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }
        #endregion
        #region Public Methods
        public void Shutdown()
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                _EditorTools.Close();
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }
        public void UpdateCounter(Counter counter)
        {
            Counter c = (Counter)_Parts.Find(p => p.Name == counter.Name);
            if (c == null)
            {
                _Parts.Add(counter);
            }
            else
            {
                c.Location = counter.Location;
                c.Rotation = counter.Rotation;
                c.VisibleToPlayers = counter.VisibleToPlayers;
            }
        }
        public Bitmap GenerateBitmap()
        {
            Bitmap bmap = null;
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                bmap = new Bitmap(this.Width, this.Height);
                using (Graphics g = Graphics.FromImage(bmap))
                {
                    #region Set Angles
                    float ClockwiseAngle = (float)((double)_ClockwiseRotation * Math.PI / Math.PI);
                    float CounterClockwiseAngle = (float)((double)_CounterclockwiseRotation * Math.PI / Math.PI);
                    #endregion

                    _ViewRectangle = new Rectangle(_ViewTopLeft.X, _ViewTopLeft.Y, this.Width / 50, this.Height / 50);
                    Pen linePen = new Pen(Color.DarkGreen, 1f);

                    g.Clear(Color.Black);
                    for (int y = 0; y < this.Height; y += 50)
                    {
                        g.DrawLine(linePen, new Point(0, y), new Point(this.Width, y));
                    }

                    for (int x = 0; x < this.Width; x += 50)
                    {
                        g.DrawLine(linePen, new Point(x, 0), new Point(x, this.Height));
                    }
                    lock (_Parts)
                    {
                        #region Draw Floors
                        // first we draw the floors that are located within the view rectangle extent
                        foreach (Floor floor in _Parts.FindAll(p => p.PartType == PartTypes.Floor && p.LocatedIn(_ViewRectangle)))
                        {
                            Point fPoint = new Point((floor.Location.X * 50) - (_ViewTopLeft.X * 50), (floor.Location.Y * 50) - (_ViewTopLeft.Y * 50));
                            Size s = ImageLibrary.Instance.GetImageFromLibrary(floor.ImageName).Size;
                            Matrix m = new Matrix();
                            float angle = (float)((double)floor.Rotation * Math.PI / Math.PI);
                            m.RotateAt(angle, new PointF(fPoint.X + (s.Width / 2), fPoint.Y + (s.Height / 2)));
                            g.Transform = m;
                            g.DrawImage(ImageLibrary.Instance.GetImageFromLibrary(floor.ImageName), fPoint);
                            g.ResetTransform();
                        }
                        #endregion
                        #region Draw Walls
                        // first we draw the Walls that are located within the view rectangle extent
                        foreach (Wall Wall in _Parts.FindAll(p => p.PartType == PartTypes.Wall && p.LocatedIn(_ViewRectangle)))
                        {
                            Point fPoint = new Point((Wall.Location.X * 50) - (_ViewTopLeft.X * 50), (Wall.Location.Y * 50) - (_ViewTopLeft.Y * 50));
                            Size s = ImageLibrary.Instance.GetImageFromLibrary(Wall.ImageName).Size;
                            Matrix m = new Matrix();
                            float angle = (float)((double)Wall.Rotation * Math.PI / Math.PI);
                            m.RotateAt(angle, new PointF(fPoint.X + (s.Width / 2), fPoint.Y + (s.Height / 2)));
                            g.Transform = m;
                            g.DrawImage(ImageLibrary.Instance.GetImageFromLibrary(Wall.ImageName), fPoint);
                            g.ResetTransform();
                        }
                        #endregion
                        #region Draw Doors
                        // then we draw the door that are located within the view rectangle extent
                        foreach (Door door in _Parts.FindAll(p => p.PartType == PartTypes.Door && p.LocatedIn(_ViewRectangle)))
                        {
                            Point dPoint = new Point((door.Location.X * 50) - (_ViewTopLeft.X * 50), (door.Location.Y * 50) - (_ViewTopLeft.Y * 50));
                            Size s = ImageLibrary.Instance.GetImageFromLibrary(door.ImageName).Size;
                            Matrix m = new Matrix();
                            float angle = (float)((double)door.Rotation * Math.PI / Math.PI);
                            m.RotateAt(angle, new PointF(dPoint.X + (s.Width / 2), dPoint.Y + (s.Height / 2)));
                            g.Transform = m;
                            g.DrawImage(ImageLibrary.Instance.GetImageFromLibrary(door.ImageName), dPoint);
                            g.ResetTransform();
                        }
                        #endregion
                        #region Draw Scenery
                        // next we draw scenery items (these are trees, furniture, chests, etc) that are located within the view rectangle extent
                        foreach (Scenery scenery in _Parts.FindAll(p => p.PartType == PartTypes.Scenery && p.LocatedIn(_ViewRectangle)))
                        {
                            // if PlayerGuid has not been set (edit mode or GM mode), or the part is visible to all players, then display it
                            if (PlayerGuid == null || PlayerGuid == new Guid() || scenery.VisibleToPlayers)
                            {
                                Point fPoint = new Point((scenery.Location.X * 50) - (_ViewTopLeft.X * 50), (scenery.Location.Y * 50) - (_ViewTopLeft.Y * 50));
                                Size s = ImageLibrary.Instance.GetImageFromLibrary(scenery.ImageName).Size;
                                Matrix m = new Matrix();
                                float angle = (float)((double)scenery.Rotation * Math.PI / Math.PI);
                                m.RotateAt(angle, new PointF(fPoint.X + (s.Width / 2), fPoint.Y + (s.Height / 2)));
                                g.Transform = m;
                                g.DrawImage(ImageLibrary.Instance.GetImageFromLibrary(scenery.ImageName), fPoint);
                                g.ResetTransform();
                            }

                        }
                        #endregion
                        #region Draw Traps
                        #endregion
                        #region Draw Counters
                        // finally we draw the counters
                        foreach (Counter counter in _Parts.FindAll(p => p.PartType == PartTypes.Counter && p.LocatedIn(_ViewRectangle)))
                        {
                            // if PlayerGuid has not been set (edit mode or GM mode), or the part is visible to all players, then display it
                            if (PlayerGuid == null || PlayerGuid == new Guid() || counter.VisibleToPlayers)
                            {
                                Point fPoint = new Point((counter.Location.X * 50) - (_ViewTopLeft.X * 50), (counter.Location.Y * 50) - (_ViewTopLeft.Y * 50));
                                Size s = ImageLibrary.Instance.GetImageFromLibrary(counter.ImageName).Size;
                                Matrix m = new Matrix();
                                float angle = (float)((double)counter.Rotation * Math.PI / Math.PI);
                                m.RotateAt(angle, new PointF(fPoint.X + (s.Width / 2), fPoint.Y + (s.Height / 2)));
                                g.Transform = m;
                                g.DrawImage(ImageLibrary.Instance.GetImageFromLibrary(counter.ImageName, 2, true, counter.CounterID, counter.IDLocation), fPoint);
                                g.ResetTransform();
                            }

                        }
                        #endregion
                        #region Draw Effects
                        // first we draw the Effects that are located within the view rectangle extent
                        foreach (Effect Effect in _Parts.FindAll(p => p.PartType == PartTypes.Effect && p.LocatedIn(_ViewRectangle)))
                        {
                            Point fPoint = new Point((Effect.Location.X * 50) - (_ViewTopLeft.X * 50), (Effect.Location.Y * 50) - (_ViewTopLeft.Y * 50));
                            Size s = ImageLibrary.Instance.GetImageFromLibrary(Effect.ImageName).Size;
                            Matrix m = new Matrix();
                            float angle = (float)((double)Effect.Rotation * Math.PI / Math.PI);
                            m.RotateAt(angle, new PointF(fPoint.X + (s.Width / 2), fPoint.Y + (s.Height / 2)));
                            g.Transform = m;
                            g.DrawImage(ImageLibrary.Instance.GetImageFromLibrary(Effect.ImageName), fPoint);
                            g.ResetTransform();
                        }
                        #endregion
                        #region Draw Markups
                        // first we draw the Markups that are located within the view rectangle extent
                        foreach (Markup Markup in _Parts.FindAll(p => p.PartType == PartTypes.Markup && p.LocatedIn(_ViewRectangle)))
                        {
                            Point fPoint = new Point((Markup.Location.X * 50) - (_ViewTopLeft.X * 50), (Markup.Location.Y * 50) - (_ViewTopLeft.Y * 50));
                            Size s = ImageLibrary.Instance.GetImageFromLibrary(Markup.ImageName).Size;
                            Matrix m = new Matrix();
                            float angle = (float)((double)Markup.Rotation * Math.PI / Math.PI);
                            m.RotateAt(angle, new PointF(fPoint.X + (s.Width / 2), fPoint.Y + (s.Height / 2)));
                            g.Transform = m;
                            g.DrawImage(ImageLibrary.Instance.GetImageFromLibrary(Markup.ImageName), fPoint);
                            g.ResetTransform();
                        }
                        #endregion
                    }
                    #region Increment and Decrement Rotations
                    _ClockwiseRotation++;
                    if (_ClockwiseRotation > 359)
                    {
                        _ClockwiseRotation = 0;
                    }
                    _CounterclockwiseRotation--;
                    if (_ClockwiseRotation < 0)
                    {
                        _CounterclockwiseRotation = 359;
                    }
                    #endregion
                    if (_ScrollOn)
                    {
                        _ScrollIndex++;
                        if (_ScrollIndex > _ScrollSpeed)
                        {
                            _ScrollIndex = 0;
                            _ViewTopLeft.X += _DeltaX;
                            _ViewTopLeft.Y += _DeltaY;
                            if (_ViewTopLeft.X < 0)
                            {
                                _ViewTopLeft.X = 0;
                            }
                            if (_ViewTopLeft.Y < 0)
                            {
                                _ViewTopLeft.Y = 0;
                            }
                        }
                    }
                    #region DisplaySelectedSlot
                    Rectangle SelRect = new Rectangle((_BoardPoint.X - _ViewTopLeft.X) * 50, (_BoardPoint.Y - _ViewTopLeft.Y) * 50, 50, 50);
                    g.DrawRectangle(new Pen(new SolidBrush(Color.Blue), 1f), SelRect);
                    #endregion
                }
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
            return bmap;
        }
        #endregion

        #region Private Events
        #region _EditorTools_RotateCounterClockwiseClicked
        /// <summary>
        /// Event from Editor Tools requesting counter clockwise rotation of part
        /// </summary>
        void _EditorTools_RotateCounterClockwiseClicked()
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                if (_EditingPartIndex > -1)
                {
                    lock (_Parts)
                    {
                        _Parts[_EditingPartIndex].Rotation -= 15;
                        if (_Parts[_EditingPartIndex].Rotation < -359)
                        {
                            _Parts[_EditingPartIndex].Rotation = 0;
                        }
                    }
                }
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }
        #endregion
        #region _EditorTools_RotateClockwiseClicked
        /// <summary>
        /// Event from Editor Tools requesting clockwise rotation of part
        /// </summary>
        void _EditorTools_RotateClockwiseClicked()
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                if (_EditingPartIndex > -1)
                {
                    lock (_Parts)
                    {
                        _Parts[_EditingPartIndex].Rotation += 15;
                        if (_Parts[_EditingPartIndex].Rotation > 359)
                        {
                            _Parts[_EditingPartIndex].Rotation = 0;
                        }
                    }
                }
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }
        #endregion
        #region _EditorTools_DeleteClicked
        /// <summary>
        /// Event from Editor Tools requesting deletion of part
        /// </summary>
        void _EditorTools_DeleteClicked()
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                if (_EditingPartIndex > -1)
                {
                    lock (_Parts)
                    {
                        _Parts.RemoveAt(_EditingPartIndex);
                        _EditingPartIndex = -1;
                    }
                }
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }
        #endregion
        #region OnPaint
        /// <summary>
        /// Override of paint event to draw all the map parts
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                if (!BitmapOnly)
                {
                    e.Graphics.Clear(Color.Black);
                    e.Graphics.DrawImage(GenerateBitmap(), new Point(0, 0));
                    this.Invalidate();
                }
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }
        #endregion
        #region MapControl_Load
        private void MapControl_Load(object sender, EventArgs e)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                DeactivateEditingTools();
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }
        #endregion
        #region MapControl_MouseMove
        private void MapControl_MouseMove(object sender, MouseEventArgs e)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                if (!_EditorTools.Visible)
                {
                    _BoardPoint = new Point((e.X / 50) + _ViewTopLeft.X, (e.Y / 50) + _ViewTopLeft.Y);
                    _DeltaY = 0;
                    _DeltaX = 0;
                    if (e.X >= 0 && e.X <= 10)
                    {
                        _DeltaX = -1;
                    }
                    else if (e.X >= this.Width - 11 && e.X <= this.Width - 1)
                    {
                        _DeltaX = 1;
                    }
                    if (e.Y >= 0 && e.Y <= 10)
                    {
                        _DeltaY = -1;
                    }
                    else if (e.Y >= this.Height - 11 && e.Y <= this.Height - 1)
                    {
                        _DeltaY = 1;
                    }

                    if (_DeltaX == -1)
                    {
                        if (_DeltaY == -1)
                        {
                            this.Cursor = Cursors.PanNW;
                        }
                        else if (_DeltaY == 1)
                        {
                            this.Cursor = Cursors.PanSW;
                        }
                        else
                        {
                            this.Cursor = Cursors.PanWest;
                        }
                    }
                    else if (_DeltaX == 1)
                    {
                        if (_DeltaY == -1)
                        {
                            this.Cursor = Cursors.PanNE;
                        }
                        else if (_DeltaY == 1)
                        {
                            this.Cursor = Cursors.PanSE;
                        }
                        else
                        {
                            this.Cursor = Cursors.PanEast;
                        }
                    }
                    else
                    {
                        if (_DeltaY == -1)
                        {
                            this.Cursor = Cursors.PanNorth;
                        }
                        else if (_DeltaY == 1)
                        {
                            this.Cursor = Cursors.PanSouth;
                        }
                        else
                        {
                            this.Cursor = Cursors.Default;

                        }
                    }

                }
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }
        #endregion
        #region MapControl_MouseClick
        private void MapControl_MouseClick(object sender, MouseEventArgs e)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                _BoardPoint = new Point((e.X / 50) + _ViewTopLeft.X, (e.Y / 50) + _ViewTopLeft.Y);
                if (e.Button == System.Windows.Forms.MouseButtons.Left) // edit mode responds to left click, as does counter selection
                {

                    DeactivateEditingTools();
                    if (EditMode)
                    {
                        if (this.Cursor == Cursors.Default)
                        {
                            try
                            {
                                _EditingPartIndex = _Parts.IndexOf(_Parts.Find(p => p.Contains(_BoardPoint) && p.PartType == _SelectedPartType));
                            }
                            catch
                            {
                                _EditingPartIndex = -1;
                            }
                            if (_EditingPartIndex != -1)
                            {
                                ActivateEditingTools(_BoardPoint);
                            }
                            else
                            {
                                if (this.SelectedPart != null)
                                {
                                    IPart newPart = this.SelectedPart.ClonePart();
                                    newPart.Location = _BoardPoint;
                                    _Parts.Add(newPart);
                                }
                            }
                        }
                    }

                    else
                    {
                        if (_SelectedCounter == null)
                        {
                            // select the counter that either belongs to the player or we are in GM mode
                            try
                            {
                                _SelectedCounter = (Counter)_Parts.Find(p => p.Contains(_BoardPoint) && p.PartType == PartTypes.Counter);
                                if (_SelectedCounter.PlayerID != PlayerGuid && !GMMode)
                                {
                                    _SelectedCounter = null;
                                }
                                else
                                {
                                    _Parts.Remove(_SelectedCounter);
                                }
                            }
                            catch
                            {
                                // doesn't exist
                            }
                        }
                        else
                        {
                            // try to place the counter at the new location
                            int partHere = -1;
                            try
                            {
                                partHere = _Parts.IndexOf(_Parts.Find(p => p.Contains(_BoardPoint)));
                            }
                            catch
                            {
                                partHere = -1;
                            }
                        }
                    }
                }
                else
                {
                    _EditorTools.Visible = false;
                }
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }
        #endregion
        #endregion
        #region Private Methods
        private void DeactivateEditingTools()
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                if (_EditorTools.Visible)
                {
                    _EditorTools.Visible = false;
                }
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }
        private void ActivateEditingTools(Point BoardPoint)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                Point screenPoint = new Point();
                Tools.GetCursorPos(ref screenPoint);
                _EditorTools.Location = new Point(screenPoint.X - 75, screenPoint.Y - 50);
                _EditorTools.Visible = true;
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }
        #endregion

    

        #region IHandleMessagesOfType<SelectedPartChangeEvent> Members

        public void HandleMessage(SelectedPartChangeEvent message)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                this.SelectedPart = message.Part;
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }

        #endregion

        #region IHandleMessagesOfType<SelectedPartTypeChangeEvent> Members

        public void HandleMessage(SelectedPartTypeChangeEvent message)
        {
            _SelectedPartType = message.PartType;
        }

        #endregion

        private void MapControl_MouseUp(object sender, MouseEventArgs e)
        {
            _ScrollOn = false;
            _ScrollIndex = 0;
        }

        private void MapControl_MouseDown(object sender, MouseEventArgs e)
        {
            _ScrollOn = true;

        }

    }
}